﻿using LibNiconico.NiconicoApi.Extentions;
using LibNiconico.NiconicoApi.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace LibNiconico.NiconicoApi.Internal
{
    /// <summary>
    /// XML形式のニコニコAPI情報レスポンスベースジェネリッククラス
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public abstract class NicoApiInfoXmlResponseBase<T>
    {
        /// <summary>
        /// APIから返されたステータス
        /// </summary>
        public NicoApiResponseStatus Status
        {
            get;
            private set;
        }

        /// <summary>
        /// エラーコード
        /// </summary>
        public T Error
        {
            get;
            private set;
        }


        /// <summary>
        /// API情報取得成功判定
        /// </summary>
        public bool Succeed
        {
            get
            {
                return Status.Code == NicoApiResponseStatusCode.OK;
            }
        }

        /// <summary>
        /// サーバ接続時間
        /// </summary>
        public DateTime Time
        {
            get;
            private set;
        }

        internal  NicoApiInfoXmlResponseBase(XDocument document)
        {
            var playerStatus = ParseStatus(document);
            switch(playerStatus.ToLower())
            {
                case "ok":
                    Status = new NicoApiResponseStatus(NicoApiResponseStatusCode.OK, playerStatus);
                    break;

                case "fail":
                    Status = new NicoApiResponseStatus(NicoApiResponseStatusCode.Fail, playerStatus);
                    break;

                default:
                    Status = new NicoApiResponseStatus(NicoApiResponseStatusCode.Undefined, playerStatus);
                    break;
            }
         
            Error = ParseErrorCode(ParseError(document));
            Time = ParseTime(document);
        }
        private  static string ParseStatus(XDocument document)
        {
            IEnumerator<XElement> list = document.Elements().GetEnumerator();
            if (list.MoveNext())
            {
                return XElementExtention.GetAttributeAsString(list.Current, "status");

            }

            return "";
        }

        private static DateTime ParseTime(XDocument document)
        {
            IEnumerator<XElement> list = document.Elements().GetEnumerator();
            if (list.MoveNext())
            {
                return DateTimeExtention.FromUnixTime( XElementExtention.GetAttributeAsLong(list.Current, "time"));

            }

            return default(DateTime);
        }

        /// <summary>
        /// コード解析
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        protected abstract T ParseErrorCode(string code);

        private static string ParseError(XDocument document)
        {
            var elements = document.Elements();
            var rslts = from element in elements.Elements("error")
                   select element != null ? XElementExtention.GetElementAsString(element, "code") : "";

            if (rslts.Count() >=1)
            {
                var enumrator = rslts.GetEnumerator();
                enumrator.MoveNext();
                return enumrator.Current;
            }
            else
            {
                return "";
            }

        }


    }


    /// <summary>
    /// XML形式のニコニコAPI情報レスポンスベースクラス
    /// </summary>
    public class NicoApiInfoXmlResponseBase : NicoApiInfoXmlResponseBase<NicoApiError>
    {
        internal NicoApiInfoXmlResponseBase(XDocument document) : base(document) { }

        /// <summary>
        /// コード解析
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        protected override NicoApiError ParseErrorCode(string code)
        {
            return NicoApiError.CreateFromResultCode(code);
        }
    }
}
